using System;
using dnAnalytics.Statistics.Distributions;
using NUnit.Framework;

namespace dnAnalytics.Tests.Statistics.Distributions
{
    [TestFixture]
    public class InverseGammaTests
    {
        private const double mAcceptableError = 1e-12;

        [Test]
        public void InverseGammaTest()
        {
            InverseGamma igamma = new InverseGamma(10.0, 3.0);

            Assert.AreEqual(igamma.A, 10.0);
            Assert.AreEqual(igamma.B, 3.0);

            Assert.AreEqual(3.0 / 9.0, igamma.Mean, mAcceptableError);
            Assert.AreEqual(System.Math.Sqrt(3.0 * 3.0 / (9.0 * 9.0 * 8.0)), igamma.StdDev, mAcceptableError);
            Assert.AreEqual(3.0 * 3.0 / (9.0 * 9.0 * 8.0), igamma.Variance, mAcceptableError);
            Assert.AreEqual(3.0 / 11.0, igamma.Mode, mAcceptableError);

            Assert.AreEqual(0.00810151179468143, igamma.Density(1.0), mAcceptableError);
            Assert.AreEqual(0.00001772873870285092, igamma.Density(2.0), mAcceptableError);

            Assert.AreEqual(-4.815704593400373, igamma.DensityLn(1.0), mAcceptableError);
            Assert.AreEqual(-10.94032357955977, igamma.DensityLn(2.0), mAcceptableError);

            Assert.AreEqual(7.121750862815578e-6, igamma.CumulativeDistribution(0.1), mAcceptableError);
            Assert.AreEqual(0.998897511869884, igamma.CumulativeDistribution(1.0), mAcceptableError);
            Assert.AreEqual(0.999999999033028, igamma.CumulativeDistribution(5.0), mAcceptableError);

        }

        [Test]
        public void GetSetRNG()
        {
            InverseGamma igamma = new InverseGamma(10.0, 3.0);

            // Try getting the random number generator.
            System.Random rnd = igamma.RandomNumberGenerator;
            // Try setting the random number generator.
            igamma.RandomNumberGenerator = new System.Random();
        }

        [Test]
        public void TrySampler()
        {
            InverseGamma igamma = new InverseGamma(10.0, 3.0);

            double s = igamma.Sample();
            double[] t = igamma.Sample(2);

            double v = InverseGamma.Sample(new System.Random(), 10.0, 3.0);
            double[] w = InverseGamma.Sample(new System.Random(), 2, 10.0, 3.0);
        }

        [TestCase(-1.0, 10.0, ExpectedException = typeof(ArgumentOutOfRangeException))]
        [TestCase(1.0, -10.0, ExpectedException = typeof(ArgumentOutOfRangeException))]
        public void InvalidParams(double a, double b)
        {
            InverseGamma g = new InverseGamma(a, b);
        }
    }
}